﻿using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;

namespace pendina.transceiver.framework
{
    public class transceiver_core : IDisposable
    {
        private IntPtr _nativeTRX;

        [DllImport("pendina_trx_framework.dll")] // the cpp framework
        static private extern IntPtr CreateTransceiver();

        [DllImport("pendina_trx_framework.dll")] // the cpp framework
        static private extern void DestroyTransceiver(IntPtr pRef);

        [DllImport("pendina_trx_framework.dll")] // the cpp framework
        static private extern void StartTransceiver(IntPtr pRef);

        [DllImport("pendina_trx_framework.dll")] // the cpp framework
        static private extern void StopTransceiver(IntPtr pRef);

        [DllImport("pendina_trx_framework.dll")] // the cpp framework
        static private extern void ResetTransceiver(IntPtr pRef);

        [DllImport("pendina_trx_framework.dll")]
        static private extern uint send_data(IntPtr pref, IntPtr data, uint size);
        [DllImport("pendina_trx_framework.dll")]
        static private extern uint get_data(IntPtr pref, out IntPtr data);
        [DllImport("pendina_trx_framework.dll")]
        static private extern void free_data(IntPtr pref, ref IntPtr data);

        public void reset()
        {
            try
            {
                ResetTransceiver(_nativeTRX);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("--> TRX Core reset failed");
                Console.WriteLine("{0}", e);
            }
        }
        public void start()
        {
            try
            {
                StartTransceiver(_nativeTRX);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("--> TRX Core start failed");
                Console.WriteLine("{0}", e);
            }
        }
        public void stop()
        {
            try
            {
                StopTransceiver(_nativeTRX);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("--> TRX Core stop failed");
                Console.WriteLine("{0}", e);
            }
        }

        public void send(Hashtable data)
        {
            try
            {
                using (MemoryStream memStream = new MemoryStream())
                {
                    BinaryWriter writer = new BinaryWriter(memStream);
				    writer.Write(33);
                    writer.Write(333);
                    writer.Write(3333);

                    GCHandle rawDataHandle = GCHandle.Alloc(memStream.GetBuffer(), GCHandleType.Pinned);
                    IntPtr address = rawDataHandle.AddrOfPinnedObject();
                    send_data(_nativeTRX, address, (uint)memStream.Length);
                    rawDataHandle.Free();
                }
            }
            catch
            {
                Console.Error.WriteLine("--> Transceiver send failed");
                Console.Error.WriteLine("--> " + DateTime.Now.ToString());
            }
        }

        public MemoryStream update()
        {
            try
            {
                IntPtr dataRef = IntPtr.Zero;
                uint len = get_data(_nativeTRX, out dataRef);
                if (len > 0)
                {
                    byte[] raw = new byte[len];
                    Marshal.Copy(dataRef, raw, 0, (int)len);
                    free_data(_nativeTRX, ref dataRef); // free dll memory

                    //
                    MemoryStream memStream = new MemoryStream(raw);
                    return memStream;
                }
                return null;
            }
            catch
            {
                Console.Error.WriteLine("--> Transceiver receive failed");
                Console.Error.WriteLine("--> " + DateTime.Now.ToString());
                return null;
            }
        }

        public transceiver_core()
        {
            try
            {
                _nativeTRX = CreateTransceiver();

                if (_nativeTRX != IntPtr.Zero)
                    Console.Error.WriteLine("--> TRX Core created");
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("--> TRX Core creation failed");
                Console.WriteLine("{0}", e);
            }
            finally
            {
                Console.Error.WriteLine("--> " + DateTime.Now.ToString());
            }
        }

        // Called when Garbage collection occurs, but only if 
        // the IDisposable.Dispose method wasn't already called
        ~transceiver_core()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
        }

        void Dispose(bool bDisposing)
        {
            if (_nativeTRX != IntPtr.Zero)
            {
                try
                {
                    DestroyTransceiver(_nativeTRX);
                    Console.Error.WriteLine("--> TRX Core destroyed");
                }
                catch
                {
                    Console.Error.WriteLine("--> TRX Core destruction failed");
                }
                finally
                {
                    Console.Error.WriteLine("--> " + DateTime.Now.ToString());
                }
            }

            if (bDisposing)
                GC.SuppressFinalize(this);
        }
    }
}
